#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# $File: dump.py
# $Date: Sun Jun 17 23:43:26 2012 +0800
# $Author: jiakai <jia.kai66@gmail.com>

from subprocess import Popen, PIPE
import sys

def system_get_stdout(cmd):
    p = Popen(cmd, stdout=PIPE, stderr=PIPE)
    (stdout, stderr) = p.communicate()
    if p.returncode == 0:
        return stdout
    raise ValueError(stderrdata)

def get_code(obj):
    res = ''
    for line in system_get_stdout(['objdump', '-d', obj]).splitlines():
        cols = line.split('\t')
        if len(cols) > 2:
            for b in [b for b in cols[1].split(' ') if b != '']:
                res += chr(int(b, 16))
        else:
            if 'data_pos' in cols[0]:
                return res
    raise ValueError('data_pos not found')

def get_data(obj):

    def get_data_offset():
        sym_tbl = [[j for j in i.split(' ') if j] for i in system_get_stdout(['objdump', '--syms',
            obj]).splitlines()[4:]]
        def find_addr(sym):
            for i in sym_tbl:
                if len(i) == 4 and i[3] == sym:
                    return int(i[0], 16)
            raise ValueError('symbol %s not found' % sym)
        return find_addr('data_pos') - find_addr('_start')

    def get_code_offset_and_size():
        addr = [i for i in system_get_stdout(
            ['objdump', '-h', obj]).splitlines()[5].split(' ') if i]
        if addr[1] != '.text':
            raise ValueError("expected .text not found in headers")
        return [int(addr[5], 16), int(addr[2], 16)]

    [off, size] = get_code_offset_and_size()
    with open(obj, 'rb') as f:
        data = f.read()
        return data[off:off+size][get_data_offset():]

def get_shell_code(obj):
    return get_code(obj) + get_data(obj)

def trans_code(s):
    ret = '"'
    for i in s:
        ret += '\\x%.2x' % ord(i)
    return ret + '"'
 
if __name__ == '__main__':
    if len(sys.argv) < 2:
        print 'Usage: %s <obj_file>' % sys.argv[0]
        sys.exit(2)
    print trans_code(get_shell_code(sys.argv[1]))
